{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f7c6feac",
   "metadata": {},
   "source": [
    "# Bibliothèques de fonctions\n",
    "\n",
    "\n",
    "Python dispose d'un ensemble de fonctions toujours accessibles. Nous en avons vu quelques une : `print`, `input`, `int`, `str`, `type`, `id`. On parle de **fonctions natives** (\"built-in\" en anglais). La liste de toutes ces fonctions et leur fonctionnement est disponible sur la [documentation](https://docs.python.org/3.7/library/functions.html) de Python 3.7. Nous allons découvrir la plus part de ces fonctions durant le cours.\n",
    "\n",
    "Pour étendre les possibilités du langage, il est possible d'importer des modules supplémentaires. Un module est un ensemble de fonctions. Certains modules forment ce que l'on appelle la [bibliothèque standard](https://docs.python.org/3.7/library/index.html). Ils sont présents sur toute machine disposant de Python. D'autres modules sont des bibliothèques additionnelles qui doivent être installés en plus. Une fois qu'un module a été installé, il peut être utilisé comme n'importe quel module de la bibliothèque standard.\n",
    "\n",
    "\n",
    "## Importer un module\n",
    "\n",
    "Pour importer un module, on utilise le mot clef `import` suivit du nom du module que l'on souhaite. Par exemple, pour disposer de fonction de tirage aléatoire, on importe le module `random` ([documentation](https://docs.python.org/3.7/library/random.html)). Le module doit être importé une fois à chaque exécution du programme.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5039efe4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import random"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65e281bb",
   "metadata": {},
   "source": [
    "On peut alors utiliser les fonctions en les préfixant par le nom du module. Par exemple si l'on souhaite utiliser la fonction `randint(a,b)` (*Return a random integer N such that a <= N <= b.*) on doit écrire `random.randint(a,b)`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f7d83f84",
   "metadata": {},
   "outputs": [],
   "source": [
    "random.randint(0,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf447b54",
   "metadata": {},
   "source": [
    "Ce peut être un peu pénible si la fonction `randint` est utilisée un grand nombre de fois. Une autre solution est de ne pas importer le module mais les fonctions du module. On peut importer juste la fonction `randint`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fae32b7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from random import randint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f72686f8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "randint(0,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb0c1d84",
   "metadata": {},
   "source": [
    "On peut également importer toutes les fonctions du modules. On peut par exemple accéder à la fonction `unform(a,b)` ([documentation](https://docs.python.org/3.7/library/random.html#random.uniform) : *Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.*)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87cd3b22",
   "metadata": {},
   "outputs": [],
   "source": [
    "from random import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8626c579",
   "metadata": {},
   "outputs": [],
   "source": [
    "uniform(0, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "536e8c5b",
   "metadata": {},
   "source": [
    "Attention, après avoir importer l'intégralité des fonctions contenues dans `random` il devient impossible de d'accéder à la fonction `randint` en utilisant la première notation : `random.randint`. On obtient une erreur cryptique : `AttributeError: 'builtin_function_or_method' object has no attribute 'randint'`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acdc5cdd",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "random.randint(0,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b5d0168",
   "metadata": {},
   "source": [
    "Il se trouve que le module `random` contient une fonction `random()` ([documentation](https://docs.python.org/3.7/library/random.html#random.random) : *return the next random floating point number in the range \\[0.0, 1.0)*). Lorsque l'on importe cette fonction avec l'instruction `from random import *`, on masque le module `random` que l'on avait importé au tout début.\n",
    "\n",
    "Il faut donc être vigilent et privilégier l'import des seules fonctions dont on a besoin."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "273ea9f4",
   "metadata": {},
   "source": [
    "## Bibliothèques additionnelles\n",
    "\n",
    "Il existe un très grand nombre de modules additionnels, la plus part s'intalleront de la même manière. Nous allons le voir rapidement avec un premier module de géographie, `folium`, qui permet d'afficher des cartes sous forme de page web.\n",
    "\n",
    "Suivant la manière dont votre installation de Python a été réalisé sur votre machine, il va exister différentes façons d'installer ce module. La plus simple est probablement d'utiliser le gestionnaire de bibliothèque de Python : `pip`. L'installation de `folium` consiste simplement à ouvrir un terminal et taper : `pip install folium`.\n",
    "\n",
    "Si vous utilisez Anaconda, vous pouvez également utiliser son interface, ouvrir la page dédiée aux modules et demander l'installation de `folium`. \n",
    "\n",
    "Dans notre cas, c'est encore plus simple. Replit installe automatiquement les packages lorsqu'on les utilise.\n",
    "\n",
    "\n",
    "Une fois l'installation faite, nous allons pour importer folium et afficher une carte.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1ab41625",
   "metadata": {},
   "outputs": [],
   "source": [
    "import folium"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c938614d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe srcdoc=\"&lt;!DOCTYPE html&gt;\n",
       "&lt;html&gt;\n",
       "&lt;head&gt;\n",
       "    \n",
       "    &lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;\n",
       "    \n",
       "        &lt;script&gt;\n",
       "            L_NO_TOUCH = false;\n",
       "            L_DISABLE_3D = false;\n",
       "        &lt;/script&gt;\n",
       "    \n",
       "    &lt;style&gt;html, body {width: 100%;height: 100%;margin: 0;padding: 0;}&lt;/style&gt;\n",
       "    &lt;style&gt;#map {position:absolute;top:0;bottom:0;right:0;left:0;}&lt;/style&gt;\n",
       "    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://code.jquery.com/jquery-1.12.4.min.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css&quot;/&gt;\n",
       "    \n",
       "            &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,\n",
       "                initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;\n",
       "            &lt;style&gt;\n",
       "                #map_2a9a5fcc92e263dbfa2c998e574c975b {\n",
       "                    position: relative;\n",
       "                    width: 100.0%;\n",
       "                    height: 100.0%;\n",
       "                    left: 0.0%;\n",
       "                    top: 0.0%;\n",
       "                }\n",
       "                .leaflet-container { font-size: 1rem; }\n",
       "            &lt;/style&gt;\n",
       "        \n",
       "&lt;/head&gt;\n",
       "&lt;body&gt;\n",
       "    \n",
       "    \n",
       "            &lt;div class=&quot;folium-map&quot; id=&quot;map_2a9a5fcc92e263dbfa2c998e574c975b&quot; &gt;&lt;/div&gt;\n",
       "        \n",
       "&lt;/body&gt;\n",
       "&lt;script&gt;\n",
       "    \n",
       "    \n",
       "            var map_2a9a5fcc92e263dbfa2c998e574c975b = L.map(\n",
       "                &quot;map_2a9a5fcc92e263dbfa2c998e574c975b&quot;,\n",
       "                {\n",
       "                    center: [48.82695320497729, 2.383139522722579],\n",
       "                    crs: L.CRS.EPSG3857,\n",
       "                    zoom: 10,\n",
       "                    zoomControl: true,\n",
       "                    preferCanvas: false,\n",
       "                }\n",
       "            );\n",
       "\n",
       "            \n",
       "\n",
       "        \n",
       "    \n",
       "            var tile_layer_c814f7a2c22e54cb6b40c7fc3ce03d17 = L.tileLayer(\n",
       "                &quot;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&quot;,\n",
       "                {&quot;attribution&quot;: &quot;Data by \\u0026copy; \\u003ca target=\\&quot;_blank\\&quot; href=\\&quot;http://openstreetmap.org\\&quot;\\u003eOpenStreetMap\\u003c/a\\u003e, under \\u003ca target=\\&quot;_blank\\&quot; href=\\&quot;http://www.openstreetmap.org/copyright\\&quot;\\u003eODbL\\u003c/a\\u003e.&quot;, &quot;detectRetina&quot;: false, &quot;maxNativeZoom&quot;: 18, &quot;maxZoom&quot;: 18, &quot;minZoom&quot;: 0, &quot;noWrap&quot;: false, &quot;opacity&quot;: 1, &quot;subdomains&quot;: &quot;abc&quot;, &quot;tms&quot;: false}\n",
       "            ).addTo(map_2a9a5fcc92e263dbfa2c998e574c975b);\n",
       "        \n",
       "&lt;/script&gt;\n",
       "&lt;/html&gt;\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x11705e770>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = folium.Map((48.82695320497729, 2.383139522722579))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4efd88c6",
   "metadata": {},
   "source": [
    "Dans la cellule ci-dessus nous appelons le module `folium` pour créer une carte. Pour cela, on appelle la fonction `Map` avec un paramètre un peu particulier `(48.82695320497729, 2.383139522722579)`. C'est un couple de deux nombres (les paranthèses sont importantes), nous reviendrons vite sur son fonctionnement. Il représente les coordonnées géographique du batiment Olympe de Gouges de l'université. La carte créée est ensuite affectée à la variable `m`.\n",
    "\n",
    "Replit, ne nous permet pas encore de voir la carte il faudra la sauvegarder mais avant cela, ajoutons un marqueur.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "17b78d7c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe srcdoc=\"&lt;!DOCTYPE html&gt;\n",
       "&lt;html&gt;\n",
       "&lt;head&gt;\n",
       "    \n",
       "    &lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;\n",
       "    \n",
       "        &lt;script&gt;\n",
       "            L_NO_TOUCH = false;\n",
       "            L_DISABLE_3D = false;\n",
       "        &lt;/script&gt;\n",
       "    \n",
       "    &lt;style&gt;html, body {width: 100%;height: 100%;margin: 0;padding: 0;}&lt;/style&gt;\n",
       "    &lt;style&gt;#map {position:absolute;top:0;bottom:0;right:0;left:0;}&lt;/style&gt;\n",
       "    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://code.jquery.com/jquery-1.12.4.min.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js&quot;&gt;&lt;/script&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css&quot;/&gt;\n",
       "    &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css&quot;/&gt;\n",
       "    \n",
       "            &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,\n",
       "                initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;\n",
       "            &lt;style&gt;\n",
       "                #map_2a9a5fcc92e263dbfa2c998e574c975b {\n",
       "                    position: relative;\n",
       "                    width: 100.0%;\n",
       "                    height: 100.0%;\n",
       "                    left: 0.0%;\n",
       "                    top: 0.0%;\n",
       "                }\n",
       "                .leaflet-container { font-size: 1rem; }\n",
       "            &lt;/style&gt;\n",
       "        \n",
       "&lt;/head&gt;\n",
       "&lt;body&gt;\n",
       "    \n",
       "    \n",
       "            &lt;div class=&quot;folium-map&quot; id=&quot;map_2a9a5fcc92e263dbfa2c998e574c975b&quot; &gt;&lt;/div&gt;\n",
       "        \n",
       "&lt;/body&gt;\n",
       "&lt;script&gt;\n",
       "    \n",
       "    \n",
       "            var map_2a9a5fcc92e263dbfa2c998e574c975b = L.map(\n",
       "                &quot;map_2a9a5fcc92e263dbfa2c998e574c975b&quot;,\n",
       "                {\n",
       "                    center: [48.82695320497729, 2.383139522722579],\n",
       "                    crs: L.CRS.EPSG3857,\n",
       "                    zoom: 10,\n",
       "                    zoomControl: true,\n",
       "                    preferCanvas: false,\n",
       "                }\n",
       "            );\n",
       "\n",
       "            \n",
       "\n",
       "        \n",
       "    \n",
       "            var tile_layer_c814f7a2c22e54cb6b40c7fc3ce03d17 = L.tileLayer(\n",
       "                &quot;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&quot;,\n",
       "                {&quot;attribution&quot;: &quot;Data by \\u0026copy; \\u003ca target=\\&quot;_blank\\&quot; href=\\&quot;http://openstreetmap.org\\&quot;\\u003eOpenStreetMap\\u003c/a\\u003e, under \\u003ca target=\\&quot;_blank\\&quot; href=\\&quot;http://www.openstreetmap.org/copyright\\&quot;\\u003eODbL\\u003c/a\\u003e.&quot;, &quot;detectRetina&quot;: false, &quot;maxNativeZoom&quot;: 18, &quot;maxZoom&quot;: 18, &quot;minZoom&quot;: 0, &quot;noWrap&quot;: false, &quot;opacity&quot;: 1, &quot;subdomains&quot;: &quot;abc&quot;, &quot;tms&quot;: false}\n",
       "            ).addTo(map_2a9a5fcc92e263dbfa2c998e574c975b);\n",
       "        \n",
       "    \n",
       "            var marker_a3f4d35be178ff8180f3c5b1bbeb3733 = L.marker(\n",
       "                [48.82695320497729, 2.383139522722579],\n",
       "                {}\n",
       "            ).addTo(map_2a9a5fcc92e263dbfa2c998e574c975b);\n",
       "        \n",
       "    \n",
       "            var icon_64b475b26811b6b9232634e11230305b = L.AwesomeMarkers.icon(\n",
       "                {&quot;extraClasses&quot;: &quot;fa-rotate-0&quot;, &quot;icon&quot;: &quot;info-sign&quot;, &quot;iconColor&quot;: &quot;white&quot;, &quot;markerColor&quot;: &quot;blue&quot;, &quot;prefix&quot;: &quot;glyphicon&quot;}\n",
       "            );\n",
       "            marker_a3f4d35be178ff8180f3c5b1bbeb3733.setIcon(icon_64b475b26811b6b9232634e11230305b);\n",
       "        \n",
       "    \n",
       "        var popup_419a059043827c1dd3dfc74c5851205f = L.popup({&quot;maxWidth&quot;: &quot;100%&quot;});\n",
       "\n",
       "        \n",
       "            \n",
       "                var html_7f4ade0c18746830b99a4067dc726d9f = $(`&lt;div id=&quot;html_7f4ade0c18746830b99a4067dc726d9f&quot; style=&quot;width: 100.0%; height: 100.0%;&quot;&gt;Olympe de Gouges&lt;/div&gt;`)[0];\n",
       "                popup_419a059043827c1dd3dfc74c5851205f.setContent(html_7f4ade0c18746830b99a4067dc726d9f);\n",
       "            \n",
       "        \n",
       "\n",
       "        marker_a3f4d35be178ff8180f3c5b1bbeb3733.bindPopup(popup_419a059043827c1dd3dfc74c5851205f)\n",
       "        ;\n",
       "\n",
       "        \n",
       "    \n",
       "&lt;/script&gt;\n",
       "&lt;/html&gt;\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x11705e770>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "folium.Marker(\n",
    "    location=(48.82695320497729, 2.383139522722579),\n",
    "    popup=\"Olympe de Gouges\",\n",
    "    icon=folium.Icon(color=\"blue\"),\n",
    ").add_to(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d63c220",
   "metadata": {},
   "source": [
    "Nous voici avec un marqueur sur le batiment. Il y aurait beaucoup de choses à dire sur ces quelques lignes. Nous verrons tout cela dans le détail mais nous avons besoin de prendre un peu de temps pour parler de choses assez basiques d'abord. Gardons simplement à l'esprit que nous avons à notre portée des choses pour s'amuser."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a96340f9",
   "metadata": {},
   "source": [
    "## Mise en oeuvre\n",
    "\n",
    "Nous allons maintenant pouvoir réaliser un premier programme avec tout ce que nous avons vu. Pour cela, nous n'utiliserons plus la console de [Repl](repl.com) mais allons créer un programme. Voici les étapes pour cela.\n",
    "\n",
    "Dans le dossier `TGAE` créer un projet Python intitulé `demo_folium`. Dans la partie centrale, en blanc, qui correspond au fichier `main.py`, inscrivé le code suivant.\n",
    "\n",
    "Ensuite vous pourrez exécuter votre programme en cliquant sur le boutton run, en vert. L'interpréteur Python va alors exécuté toutes les lignes contenues dans le fichier `main.py`. La première fois, c'est un peu long car Repl doit installer la bibliothèque `folium`.\n",
    "\n",
    "```{code}\n",
    "import folium\n",
    "\n",
    "m = folium.Map((48.82695320497729, 2.383139522722579))\n",
    "folium.Marker(\n",
    "    location=(48.82695320497729, 2.383139522722579),\n",
    "    popup=\"Olympe de Gouges\",\n",
    "    icon=folium.Icon(color=\"blue\"),\n",
    ").add_to(m)\n",
    "\n",
    "m.save(\"demo.html\")\n",
    "```\n",
    "\n",
    "Vous devriez voir apparaitre un fichier `demo.html` dans la partie gauche. Vous pouvez le télécharger (en cliquant sur \"...\") et l'ouvrir dans votre navigateur.\n",
    "\n",
    "![demo folium](../_static/images/demo_folium_repl.png)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f096c779",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
